home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/nodes.h>
- #include <exec/resident.h>
- #include <exec/errors.h>
- #include <libraries/expansionbase.h>
- #include <libraries/configvars.h>
- #include <devices/trackdisk.h>
-
- /*
- * Set SysBase to a local variable, that loads directly from 4 when it
- * has to be reloaded
- */
- #define BASE_EXT_DECL
- #define BASE_NAME (*(void **)4)
- #include <inline/exec.h>
- #undef PRIVATE
- #define BASE_EXT_DECL
- #define BASE_PAR_DECL void *ExpansionBase,
- #define BASE_PAR_DECL0 void *ExpansionBase
- #include <inline/expansion.h>
-
- #include <stddef.h>
-
- #include "device.h"
-
- extern void scsi_cmd();
-
- ulong func_table[];
- struct init_struct data_table;
- struct scsi_dev *init_routine();
- /*
- * small assembly glue.. needed, because these routines have to preserve ALL
- * registers..
- */
- extern ulong glue_init(), glue_scsi_expunge(), glue_scsi_open(),
- glue_scsi_close(), glue_scsi_beginio(), glue_scsi_abortio();
- DECL_DPRINTF;
- extern void try_unit (struct scsi_dev *dev, int unit);
- int expunge_unit (struct scsi_dev *dev, struct scsi_unit *unit);
-
- ulong Init[] = {
- sizeof(struct scsi_dev),
- (ulong) func_table,
- (ulong) &data_table,
- (ulong) glue_init,
- };
-
- int scsi_open(), scsi_close(), scsi_expunge(),
- scsi_beginio(), scsi_abortio(), null_func();
-
- ulong func_table[] = {
- (ulong) glue_scsi_open,
- (ulong) glue_scsi_close,
- (ulong) glue_scsi_expunge,
- (ulong) null_func,
- (ulong) glue_scsi_beginio,
- (ulong) glue_scsi_abortio,
- ~0,
- };
-
- struct init_struct {
- DECLARE_BYTE(1); DECLARE_LONG(2); DECLARE_BYTE(3); DECLARE_WORD(4);
- DECLARE_WORD(5); DECLARE_LONG(6);
- ubyte end[4];
- } data_table = {
- INITBYTE( offsetof(struct Node, ln_Type), NT_DEVICE ),
- INITLONG( offsetof(struct Node, ln_Name), SCSI_NAME ),
- INITBYTE( offsetof(struct Library, lib_Flags), LIBF_SUMUSED|LIBF_CHANGED ),
- INITWORD( offsetof(struct Library, lib_Version), SCSI_VERSION ),
- INITWORD( offsetof(struct Library, lib_Revision), SCSI_REVISION ),
- INITLONG( offsetof(struct Library, lib_IdString), SCSI_IDSTRING ),
- 0,0,0,0,
- };
-
- /*
- * those glue functions just save the trashed registers on the stack and
- * call the appropriate function with the set up argument(s)
- * Pitty gas doesn't accept comments.. or I was to stupid to guess the
- * correct syntax:-))
- */
- asm("
- .text
- .globl _glue_init
- _glue_init:
- moveml #0x7ffc,sp@-
-
- moveml #0x8080,sp@-
- jsr _init_routine
- addw #8,sp
-
- moveml sp@+,#0x3ffe
- rts
-
- .globl _glue_scsi_open
- _glue_scsi_open:
- moveml #0x7ffc,sp@-
-
- jsr _scsi_open
-
- moveml sp@+,#0x3ffe
- rts
-
- .globl _glue_scsi_close
- _glue_scsi_close:
- moveml #0x7ffc,sp@-
-
- jsr _scsi_close
-
- moveml sp@+,#0x3ffe
- rts
-
-
- .globl _glue_scsi_expunge
- _glue_scsi_expunge:
- moveml #0x7ffc,sp@-
-
- jsr _scsi_expunge
-
- moveml sp@+,#0x3ffe
- rts
-
- .globl _glue_scsi_beginio
- _glue_scsi_beginio:
- moveml #0x7ffc,sp@-
-
- jsr _scsi_beginio
-
- moveml sp@+,#0x3ffe
- rts
-
- .globl _glue_scsi_abortio
- _glue_scsi_abortio:
- moveml #0x7ffc,sp@-
-
- jsr _scsi_abortio
-
- moveml sp@+,#0x3ffe
- rts
- ");
-
- struct scsi_dev *
- init_routine(struct scsi_dev *dev, ulong seg_list, volatile ulong a1)
- {
- struct ConfigDev *cd;
- struct MsgPort *mp;
- struct Task *tcb;
- int unit;
- struct ExpansionBase *ExpansionBase;
-
- DPRINTF(("init ($%lx): seglist=$%lx, dev=$%lx", init_routine, seg_list, dev));
-
- dev->sc_seglist = seg_list;
-
- mp = &dev->sc_msgport;
- mp->mp_Node.ln_Type = NT_MSGPORT;
- mp->mp_SigBit = AllocSignal(-1);
- mp->mp_SigTask = FindTask(0);
- mp->mp_Flags = PA_SIGNAL;
- NewList(&mp->mp_MsgList);
-
- InitSemaphore(& dev->sc_semaph);
- /*
- * This will take care, that - while we're waiting later - Init won't
- * be interrupted by an OpenDevice call...
- */
- ObtainSemaphore(& dev->sc_semaph);
-
- if (ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",0))
- {
- /*
- * using FindConfigDev() instead of GetCurrentBinding() ensures,
- * that these units can be mounted without having been initialized
- * by Binddrivers.. the first mount will init the device
- */
- cd = FindConfigDev(ExpansionBase, 0, BOARD_MANUFACT, BOARD_PROCUCT);
-
- if (cd)
- {
- dev->sc_base = (ulong)cd->cd_BoardAddr;
- cd->cd_Flags &= ~CDF_CONFIGME;
-
- /*
- * now fire up the handler task, that will execute our
- * scsi command requests for us (message queues are an excellent
- * way of garanteeing single-threaded device hardware usage.. )
- */
-
- tcb = &dev->sc_htcb;
- tcb->tc_SPLower = (APTR)dev->sc_hstack;
- tcb->tc_SPUpper = (APTR)(dev->sc_hstack + HANDLER_STACKSIZE);
- tcb->tc_SPReg = (APTR)((ulong)tcb->tc_SPUpper - 4);
- /* pass the child the device pointer */
- *(struct scsi_dev **)tcb->tc_SPReg = dev;
-
- tcb->tc_Node.ln_Type = NT_TASK;
- tcb->tc_Node.ln_Pri = HANDLER_PRIORITY;
- tcb->tc_Node.ln_Name = HANDLER_NAME;
-
- NewList(&tcb->tc_MemEntry);
-
- DPRINTF(("starting handler task"));
- AddTask(tcb, scsi_cmd, 0);
-
- /*
- * wait for child to get ready.. don't know, how bad this is
- * at this point to wait - it *is* bad according to the RKM -
- * but how bad.....??
- */
- WaitPort(&dev->sc_msgport); GetMsg(&dev->sc_msgport);
- /* when this returns, dev->sc_hmsgport will be valid */
-
- DPRINTF(("Handler task ok"));
-
- /*
- * Now try to find out, which devices are connected to
- * the SCSI bus, and fire up the respective units, that mount
- * themselves as DOS nodes (not at the moment:-))
- */
- for (unit = 0; unit < 7; unit++) try_unit (dev, unit);
- }
- CloseLibrary(ExpansionBase);
- }
- DPRINTF(("scsi_init terminated"));
- ReleaseSemaphore(& dev->sc_semaph);
- return dev;
- }
-
- int
- scsi_open()
- {
- /* can't use them as regular variables, because d0/a1 are likely to
- * get used as temporary registers */
- register struct scsi_dev *dev_pass asm("a6");
- register struct IORequest *io_req_pass asm("a1");
- register int unit_pass asm("d0");
-
- struct scsi_dev *dev = dev_pass;
- struct IORequest *io_req = io_req_pass;
- int unit = unit_pass;
-
- /*
- * we will only be able to get this semaphore, when Init is completely
- * thru with its job, this was necessary, because Init breaks the Forbid
- * Exec enabled during its execution
- */
- ObtainSemaphore(& dev->sc_semaph);
-
- DPRINTF(("open: dev = $%lx, unit# = %ld, io_req = $%lx", dev, unit, io_req));
-
- /* perform validity checking on the unit range */
- if (unit >= 0 && unit <= 6)
- {
- /*
- * since we already fired up all units that exist, if the requested
- * unit doesn't have a corresponding unit task, we return with
- * an error
- */
- if (dev->sc_units[unit])
- {
- ++ dev->sc_device.dd_Library.lib_OpenCnt;
- ++ dev->sc_units[unit]->scu_unit.unit_OpenCnt;
- io_req->io_Error = 0;
- io_req->io_Unit = (struct Unit *)dev->sc_units[unit];
- dev->sc_device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
- DPRINTF(("open-ok!"));
- ReleaseSemaphore(& dev->sc_semaph);
- return 0;
- }
- }
- DPRINTF(("open-Error!"));
- ReleaseSemaphore(& dev->sc_semaph);
- io_req->io_Error = IOERR_OPENFAIL;
- return IOERR_OPENFAIL;
- }
-
- int
- scsi_close()
- {
- register struct scsi_dev *dev_pass asm("a6");
- register struct IORequest *io_req_pass asm("a1");
- struct IORequest *io_req = io_req_pass;
- struct scsi_unit *su = (struct scsi_unit *)io_req->io_Unit;
- struct scsi_dev *dev = dev_pass;
-
- DPRINTF(("close: dev = $%lx, unit = $%lx, io_req = $%lx", dev,su,io_req));
-
- io_req->io_Unit = (void *)
- io_req->io_Device = (void *)-1;
-
- if (-- su->scu_unit.unit_OpenCnt == 0)
- expunge_unit(dev, su);
-
- if (-- dev->sc_device.dd_Library.lib_OpenCnt == 0)
- {
- if (dev->sc_device.dd_Library.lib_Flags & LIBF_DELEXP)
- return scsi_expunge(dev);
- }
- return 0;
- }
-
- int
- scsi_expunge()
- {
- register struct scsi_dev *dev_pass asm("a6");
- struct scsi_dev *dev = dev_pass;
- ulong seglist;
-
- DPRINTF(("expunge: dev = $%lx", dev));
-
- #ifdef DO_EXPUNGE
-
- if (dev->sc_device.dd_Library.lib_OpenCnt > 0)
- {
- dev->sc_device.dd_Library.lib_Flags |= LIBF_DELEXP;
- return 0;
- }
-
- dev->sc_hmessage.scm_cmd = SCM_CMD_SHUTDOWN;
- PutGetMsg(dev->sc_hmsgport, &dev->sc_msgport,
- (struct Message *)&dev->sc_hmessage);
- /* handler task now shut down */
-
- Remove((struct Node *)dev);
-
- seglist = dev->sc_seglist;
-
- FreeMem(dev,
- dev->sc_device.dd_Library.lib_NegSize +
- dev->sc_device.dd_Library.lib_PosSize);
- return seglist;
- #else
-
- return 0;
- #endif
-
- }
-
- int
- null_func()
- {
- return 0;
- }
-
- int
- expunge_unit(struct scsi_dev *dev, struct scsi_unit *unit)
- {
- /* since I spawned the units at Init-time, not at Open-time, I don't
- * want to get rid of them now.. */
- return 0;
- }
-
- /****************************************************************************/
-
- int scsi_invalid(), scsi_reset(),
- scsi_read(), scsi_write(), scsi_update(), scsi_clear(), scsi_stop(),
- scsi_start(), scsi_flush(), scsi_motor(), scsi_seek(), scsi_format(),
- scsi_remove(), scsi_changenum(), scsi_changestate(), scsi_protstatus(),
- scsi_rawread(), scsi_rawwrite(), scsi_getdrivetype(),
- scsi_getnumtracks(), scsi_addchangeint(), scsi_remchangeint(),
- scsi_direct();
-
- int
- (*cmd_table []) () = {
- scsi_invalid, /* 00 */
- scsi_reset, /* 01 */
- scsi_read, /* 02 */
- scsi_write, /* 03 */
- scsi_update, /* 04 */
- scsi_clear, /* 05 */
- scsi_stop, /* 06 */
- scsi_start, /* 07 */
- scsi_flush, /* 08 */
- scsi_motor, /* 09 */
- scsi_seek, /* 10 */
- scsi_format, /* 11 */
- scsi_remove, /* 12 */
- scsi_changenum, /* 13 */
- scsi_changestate, /* 14 */
- scsi_protstatus, /* 15 */
- scsi_rawread, /* 16 */
- scsi_rawwrite, /* 17 */
- scsi_getdrivetype, /* 18 */
- scsi_getnumtracks, /* 19 */
- scsi_addchangeint, /* 20 */
- scsi_remchangeint, /* 21 */
- scsi_invalid, /* 22 */
- scsi_invalid, /* 23 */
- scsi_invalid, /* 24 */
- scsi_invalid, /* 25 */
- scsi_invalid, /* 26 */
- scsi_invalid, /* 27 */
- scsi_direct, /* 28 */
- };
-
- int
- scsi_beginio()
- {
- register struct IORequest *io_req_pass asm("a1");
- register struct scsi_dev *dev_pass asm("a6");
- struct scsi_dev *dev = dev_pass;
- struct IORequest *io_req = io_req_pass;
- struct scsi_unit *su = (struct scsi_unit *)io_req->io_Unit;
-
- if (!su) return IOERR_OPENFAIL;
-
- DPRINTF(("beginio: dev = $%lx, unit# = %ld, cmd = %ld",
- dev, su->scu_unitnum, io_req->io_Command));
-
- /*
- * in the first release of the device, the RMB bit is ignored, and
- * thus removeable mediums are not supported. To be compatible to
- * later releases, ETD-commands are just routed to their normal
- * partners..
- */
-
- io_req->io_Command &= ~TDF_EXTCOM;
- io_req->io_Message.mn_Node.ln_Type = NT_MESSAGE;
-
- if (io_req->io_Command >= 0 && io_req->io_Command <= 28)
- {
- /* no immediates supported for now.. */
- io_req->io_Flags &= ~IOF_QUICK;
- PutMsg(su->scu_cmd_mp, (struct Message *)io_req);
- return 0;
- }
- return IOERR_NOCMD;
- }
-
- int
- scsi_abortio()
- {
- return IOERR_NOCMD;
- }
-
- /* now follow all - so far - ignored commands */
-
- int
- scsi_invalid()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_reset()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_stop()
- {
- return IOERR_NOCMD;
- }
- int
- scsi_start()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_flush(struct IOStdReq *io_req)
- {
- #ifdef ENABLE_CACHE
- invalidate_cache (io_req->io_Unit);
- return 0;
- #endif
- return IOERR_NOCMD;
- }
- int
- scsi_motor()
- {
- return 0;
- }
- int
- scsi_seek()
- {
- return IOERR_NOCMD;
- }
- int
- scsi_remove()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_changenum(struct IOStdReq *io_req)
- {
- io_req->io_Actual = 1; /* always disk label 1... */
- return 0;
- }
- int
- scsi_changestate(struct IOStdReq *io_req)
- {
- io_req->io_Actual = 0; /* always a disk present?? with RMB surely not... */
- return 0;
- }
- int
- scsi_rawread()
- {
- return IOERR_NOCMD;
- }
- int
- scsi_rawwrite()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_getdrivetype(struct IOStdReq *io_req)
- {
- io_req->io_Actual = DRIVE3_5;
- return 0;
- }
-
- int
- scsi_getnumtracks(struct IOStdReq *io_req)
- {
- io_req->io_Actual = 1;
- return 0;
- }
-
- int
- scsi_clear(struct IOStdReq *io_req)
- {
- #ifdef ENABLE_CACHE
- invalidate_cache (io_req->io_Unit);
- return 0;
- #endif
- return IOERR_NOCMD;
- }
-
- int
- scsi_update()
- {
- #ifdef ENABLE_CACHE
- return 0; /* we have a write-thru cache */
- #endif
- return IOERR_NOCMD;
- }
-
- int
- scsi_addchangeint()
- {
- return IOERR_NOCMD;
- }
-
- int
- scsi_remchangeint()
- {
- return IOERR_NOCMD;
- }
-